/**
 * @description 包含发送请求的底层客户端实例，以及相关通用的响应处理函数
 */

import { showLoadingMsg } from '@/utils/msg';
import type { AxiosResponse } from 'axios';

export const baseURL = import.meta.env.VITE_API_BASE_URL;

// 发送请求使用的底层客户端实例，所有 API 请求都应该通过此客户端发送
export const $ = axios.create({
  baseURL: baseURL,
  timeout: 10000,
});

// 定义请求拦截器，设置 Authorization 请求头
$.interceptors.request.use((config) => {
  return config;
});

// 后端定义的基础响应数据结构
interface BaseResp<T> {
  code: number;
  msg: string;
  data: T;
}

/**
 * 从响应数据中提取 data 字段，如果 code 不为 0 则抛出异常
 * @param resp Axios 响应对象
 * @returns data 字段
 */
export function getDataIfCodeZero<T>(resp: AxiosResponse<BaseResp<T>>): T {
  return resp.data.data;
}

/**
 * 包装一个 Promise，使用 showLoadingMsg 显示加载中提示，直到 Promise 结束
 * @param msg 提示的文字
 * @param fn 要包装的函数
 * @param delayShow (可选) 延迟显示加载提示的时间，默认 200ms
 * @returns 包装后的 Promise
 */
export function withLoadingMsg<T>(
  msg: string,
  fn: () => Promise<T>,
  delayShow: number = 200
): Promise<T> {
  return new Promise((resolve, reject) => {
    let close: () => void;
    const timer = setTimeout(() => {
      close = showLoadingMsg(msg).close;
    }, delayShow);

    fn()
      .then(resolve)
      .catch(reject)
      .finally(() => {
        clearTimeout(timer);
        close?.();
      });
  });
}
